package com.card.game.dn;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Vector;

import com.card.common.CardContants;
import com.card.common.MessageComm;
import com.card.game.BasePlayer;
import com.card.game.BasePlayer.UserState;
import com.card.game.Card;
import com.card.game.CardUtils;
import com.card.game.room.AbstractRoom;
import com.card.game.room.RoomSetting;
import com.card.game.room.RoomState;
import com.card.match.IMatchRoom;
import com.card.message.JsonMessageCenter;
import com.card.user.RoomBack;
import com.card.user.User;
import com.card.user.UserUtils;
import com.google.common.collect.Lists;
import com.xiaoao.net.common.GameConstants;
import com.xiaoao.net.global.Global;
import com.xiaoao.net.json.message.JsonMessage;
import com.xiaoao.net.utils.StringUtil;

public class NnRoom extends AbstractRoom{
	public static final int Min_Player_Num = 2;
	private static final int Max_Watch_Num = 0;
	
	protected transient Vector<BasePlayer> watchList = new Vector<>();
	private transient long curhowsTurnStartTime;
	protected transient RoomBack roomBack;
	
//	private transient long lastStateTime;
	public boolean isCanStart;
	public transient NnRoomInfo nnRoomInfo;
	public String zhuangId;
	
	public NnRoom(String ownerId,RoomSetting roomSetting) {
		super(CardContants.GAMETYPE_Nn,ownerId);
		setRoomSetting(roomSetting);
		this.roomBack = new RoomBack(this);
		this.nnRoomInfo = new NnRoomInfo(this);
	}
	public NnRoom(NnPlayer player,RoomSetting roomSetting) {
		super(CardContants.GAMETYPE_Nn,player.getUserId());
		setRoomSetting(roomSetting);
		this.roomBack = new RoomBack(this);
		this.nnRoomInfo = new NnRoomInfo(this);
		player.setTableIndex(0);
		super.addPlayer(player);
		//通知所有人房间信息改变
		sendRoomInfo();
	}
	
	@Override
	public void addPlayer(BasePlayer player) {
		synchronized (this.playerList) {
			if(this.playerList.size()<getMaxUserNum()) {
				player.setTableIndex(this.playerList.size());
				super.addPlayer(player);
				this.isCanStart = true;
				//通知所有人房间信息改变
				sendRoomInfo();
				return;
			}
		}
	}
	
	@Override
	public boolean isFull() {
		return this.playerList.size()>=getMaxUserNum()
				&&this.watchList.size()>=Max_Watch_Num;
	}
	
	@Override
	public void doTimedTask() {
		if(this.state == RoomState.QiangDizhu) {
			if(getChangeStateTime() > 6*GameConstants.SECOND) {
				setState(RoomState.Running);
				setAllPlayerState(UserState.WaitBet);
				sendNnInfo();
				checkZhuang();
			}
		}else if(this.state == RoomState.WaitBet) {
			if(getChangeStateTime() > 6*GameConstants.SECOND) {
				setState(RoomState.Running);
				setAllPlayerState(UserState.Bet);
				if(isKanQiangZhuang()) {
					broadLastCard();
				}else{
					broadFaPai();
				}
				sendNnInfo();
				broadOpenCard();
			}
		}else if(this.state == RoomState.OpenPai) {
			if(getChangeStateTime() > 12*GameConstants.SECOND) {
				setState(RoomState.Running);
				setAllPlayerState(UserState.FapaiComplete);
//				sendNnInfo();
				calGameEnd();
			}
		}
	}
	
	@Override
	public void startGame() {
		this.playNum++;
		super.startGame();
		if(isKanQiangZhuang()) {
			broadFaPai();
			broadQiangZhuang();
			return;
		}else{
			if(this.zhuangId == null) {
				broadQiangZhuang();
				return;
			}
			if(isLunZhuang()) {
				JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_Nn_ShowZhuang);
				message.addProperty("zhuangId", this.zhuangId);
				broadcast(message);
			}
			broadStartBetMessage();
		}
	}
	
	private void broadFaPai() {
		setState(RoomState.Running);
		this.tableCards = CardUtils.createNN();
		for (int i = 0; i < playerList.size(); i++) {
			NnPlayer player = (NnPlayer)playerList.get(i);
			Vector<Card> outCard = CardUtils.faPaiToVector(this.tableCards, 5);
			player.initCards(outCard);
			if(isKanQiangZhuang()) {
				player.replaceLastCard(new Card(-1,0));
			}else{
				player.checkNiu();
			}
			sendStarGameMessage(player);
		}
		sendNnInfo();
		Global.logErrorMessage("=================总牌数"+this.tableCards.size()+"==========");
	}
	
	private void broadQiangZhuang() {
		if(this.zhuangId == null) {
			setState(RoomState.QiangDizhu);
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_Nn_QiangZhuang);
			message.addProperty("nnType", roomSetting.getNnType());
			broadcast(message);
		}
	}
	public void qiangZhuang(String userId,int score) {
		NnPlayer player = getPlayerById(userId);
		if(player.isQiang) {
			return;
		}
		player.isQiang = true;
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_DdzQiangDizhu);
		message.addProperty("userId", userId);
		message.addProperty("qiang", score);
		broadcast(message);
		player.setState(UserState.WaitBet);
		player.nnInfo.qiangScore = score;
		sendNnInfo();
		checkZhuang();
	}
	
	private void checkZhuang() {
		if(allIsState(UserState.WaitBet)) {
			this.zhuangId = chooseZhuang();
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_Nn_ShowZhuang);
			message.addProperty("zhuangId", this.zhuangId);
			broadcast(message);
			broadStartBetMessage();
		}
	}
	
	public void betAction(String userId,int score) {
		score = Math.max(1, score);
		score = Math.min(score, 4);
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_Niu_Bet);
		message.addProperty("userId", userId);
		message.addProperty("betscore", score);
		broadcast(message);
		NnPlayer player = getPlayerById(userId);
		player.setState(UserState.Bet);
		player.nnInfo.betScore = score;
		sendNnInfo();
		if(allIsState(UserState.Bet)) {
			if(isKanQiangZhuang()) {
				broadLastCard();
			}else{
				broadFaPai();
			}
			broadOpenCard();
		}
	}
	
	
	public void niuAction(String userId) {
		NnPlayer player = getPlayerById(userId);
		player.showCard();
		player.setState(UserState.FapaiComplete);
		JsonMessage message = new JsonMessage(MessageComm.S2C_ShowNiu);
		message.addProperty("userId", userId);
		message.addProperty("hand", player.getShowCards());
		message.addProperty("niuNum", player.niuNum);
		JsonMessageCenter.getInstance().sendMessage(message, player);
//		broadcast(message);
//		sendNnInfo();
//		
//		if(allIsState(UserState.End)) {
//			calGameEnd();
//		}
	}
	
	private int getNextPlayerByIndex(int tableIndex) {
        return tableIndex == getMaxUserNum() - 1 ? 0 : tableIndex + 1;
    }
	public int getPrePlayerByIndex(int tableIndex) {
        return tableIndex == 0 ? getMaxUserNum() - 1 : tableIndex - 1;
    }
	
	private void broadOpenCard() {
		setState(RoomState.OpenPai);
		for (BasePlayer temp : playerList) {
			NnPlayer player = (NnPlayer)temp;
			if(isKanQiangZhuang()) player.checkNiu();
			JsonMessage message = new JsonMessage(MessageComm.S2C_StartShow);
			message.addProperty("hand", player.getShowCards());
			message.addProperty("niuNum", player.niuNum);
			JsonMessageCenter.getInstance().sendMessage(message, player);
		}
	}
	
	private void broadStartBetMessage() {
		JsonMessage message = new JsonMessage(MessageComm.S2C_Nn_StartBet);
		for (BasePlayer basePlayer : playerList) {
			if(!StringUtil.equals(this.zhuangId, basePlayer.getUserId())) {
				JsonMessageCenter.getInstance().sendMessage(message, basePlayer);
			}else{
				basePlayer.setState(UserState.Bet);
			}
		}
		setState(RoomState.WaitBet);
	}
	
	private void broadLastCard() {
		for (BasePlayer temp : playerList) {
			NnPlayer player = (NnPlayer)temp;
			Card card = CardUtils.faPaiOne(tableCards);
			player.replaceLastCard(card);
		}
	}
	
	private void sendStarGameMessage(NnPlayer player) {
		JsonMessage message = new JsonMessage(MessageComm.S2C_StartGame);
		message.addProperty("hand", player.getShowCards());
		message.addProperty("niuNum", player.niuNum);
		JsonMessageCenter.getInstance().sendMessage(message, player);
	}
	
	@Override
	public void clearRoom() {
		super.clearRoom();
		this.nnRoomInfo = null;
		this.watchList.clear();
		this.roomBack = null;
	}
	
	public void endGame() {
		if(isWuNiuXiaZhuang()) {
			NnPlayer zhuang = getPlayerById(this.zhuangId);
			if(zhuang.niuNum <= 0) {
				NnPlayer nextZhuang = getPlayerByTableIndex(getPrePlayerByIndex(zhuang.getTableIndex()));
				this.zhuangId = nextZhuang.getUserId();
			}
		}
		if(isKanQiangZhuang()) {
			this.zhuangId = null;
		}
		if(isLunZhuang()) {
			NnPlayer zhuang = getPlayerById(this.zhuangId);
			NnPlayer nextZhuang = getPlayerByTableIndex(getPrePlayerByIndex(zhuang.getTableIndex()));
			this.zhuangId = nextZhuang.getUserId();
		}
		super.endGame();
		if(this.playNum  >= roomSetting.getMaxPlayNum()) {
			roomEnd();
			clearRoom();
			return;
		}
	}
	
	public void roomEnd() {
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_NN_ALL_END);
		message.addProperty("playerScores", getPlayerScore());
		broadcast(message);
		roomBack.loadScore(this);
		for (BasePlayer basePlayer : playerList) {
			User user = UserUtils.getUserByPrimaryKey(basePlayer.getUserId());
			if(user != null) {
				user.userPlayBacks().addNnRoomBack(roomBack);
				user.sendUserUpdateMessage();
			}
		}
	}
	
	@Override
	public void disbandRoom() {
		if(isStartGame) {
			roomEnd();
		}else{
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_RoomDisband);
			message.addProperty("firstId", ownerId);
			broadcast(message);
		}
		clearRoom();
	}
	@Override
	public void disbandAgencyRoom() {
		if(isStartGame) {
			roomEnd();
		}else{
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_DisbandAgencyCreateRoom);
			message.addProperty("firstId", ownerId);
			broadcast(message);
		}
		clearRoom();
	}
	@Override
	public void breakConnect(BasePlayer p) {
		NnPlayer player = (NnPlayer)p;
		JsonMessage message1 = new JsonMessage(MessageComm.C2S_BreakConnect);
		message1.addProperty("room", this);
		JsonMessageCenter.getInstance().sendMessage(message1, player);
		if(state == RoomState.QiangDizhu) {
			if(player.getState() != UserState.WaitBet) {
				JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_Nn_QiangZhuang);
				message.addProperty("nnType", roomSetting.getNnType());
				JsonMessageCenter.getInstance().sendMessage(message, player);
			}
		}
		if(isStartGame) {
			player.sendHandMessage();
			sendNnInfo();
			if(state == RoomState.WaitBet) {
				if(player.getState() != UserState.Bet) {
					JsonMessage message = new JsonMessage(MessageComm.S2C_Nn_StartBet);
					JsonMessageCenter.getInstance().sendMessage(message, player);
				}
			}else if(state == RoomState.OpenPai) {
				if(player.getState() != UserState.FapaiComplete) {
					JsonMessage message = new JsonMessage(MessageComm.S2C_StartShow);
					message.addProperty("hand", player.getShowCards());
					message.addProperty("niuNum", player.niuNum);
					JsonMessageCenter.getInstance().sendMessage(message, player);
				}
			}
			
		}
		player.changeOnline(true);
	} 
	public NnPlayer getPlayerById(String userId) {
		return (NnPlayer)super.getPlayerById(userId);
	}
	public NnPlayer getPlayerByTableIndex(int index) {
		return (NnPlayer)super.getPlayerByTableIndex(index);
	}
	
	private void calGameEnd() {
		setState(RoomState.End);
		NnPlayer zhuangPlayer = getPlayerById(this.zhuangId);
		int zhuangScore = zhuangPlayer.nnInfo.qiangScore;
		if(!isKanQiangZhuang()) {
			zhuangScore = 1;
		}
		zhuangScore = Math.max(1, zhuangScore);
		int zhuangBei = getBei(zhuangPlayer.nnInfo.niuNum);
		
		List<NnJuEnd> endList = Lists.newArrayList();
		for (BasePlayer basePlayer : playerList) {
			NnPlayer player = (NnPlayer)basePlayer;
			if(!StringUtil.equals(player.getUserId(), this.zhuangId)) {
				boolean winZhuang = player.nnInfo.compareTo(zhuangPlayer.nnInfo)>0;
				int betScore = Math.max(player.nnInfo.betScore, 1);
				if(winZhuang) {
					int bei = getBei(player.nnInfo.niuNum);
					int winScore = zhuangScore*bei*betScore;
					player.addWinScore(winScore);
					zhuangPlayer.addWinScore(-winScore);
				}else{
					int winScore = zhuangScore*zhuangBei*betScore;
					player.addWinScore(-winScore);
					zhuangPlayer.addWinScore(winScore);
				}
				endList.add(new NnJuEnd(player));
			}
		}
		Collections.sort(endList);
		endList.add(new NnJuEnd(zhuangPlayer));
		
//		sendNnInfo();
		JsonMessage message = new JsonMessage(MessageComm.S2C_NN_GAME_END);
		message.addProperty("nnEndList", endList);
		broadcast(message);
		this.nnRoomInfo.clear();
		endGame();
	}
	
	private List<NnInfo> getNnInfos() {
		List<NnInfo> list = Lists.newArrayList();
		for (BasePlayer p : playerList) {
			list.add(((NnPlayer)p).nnInfo);
		}
		return list;
	}
	
	public void sendNnInfo() {
		JsonMessage message = new JsonMessage(MessageComm.S2C_RoomNnInfo);
		message.addProperty("roomNuInfo", this.nnRoomInfo);
		message.addProperty("userNuInfoList", getNnInfos());
		broadcast(message);
	}
	
	@Override
	public int getMaxUserNum() {
		return roomSetting.getUserNum();
	}
	
	public String chooseZhuang() {
		List<NnInfo> infoList = Lists.newArrayList();
		for (BasePlayer p : playerList) {
			infoList.add(((NnPlayer)p).nnInfo);
		}
		Collections.sort(infoList, new Comparator<NnInfo>() {
			@Override
			public int compare(NnInfo o1, NnInfo o2) {
				return o2.qiangScore - o1.qiangScore;
			}
		});
		int winScore = infoList.get(0).qiangScore;
		List<String> ids = Lists.newArrayList();
		for (NnInfo info : infoList) {
			if(info.qiangScore == winScore) {
				ids.add(info.userId);
			}else{
				break;
			}
		}
		Collections.shuffle(ids);
		return ids.get(0);
	}
	
	public boolean isLunZhuang() {
		return this.roomSetting.getNnType() == 1;
	}
	public boolean isWuNiuXiaZhuang() {
		return this.roomSetting.getNnType() == 0;
	}
	public boolean isKanQiangZhuang() {
		return this.roomSetting.getNnType() == 2;
	}
	
	/*
	 * 三倍封顶，无牛到牛六一杯，牛789两倍，牛牛以上三倍
五倍封顶，无牛到牛六一倍，牛789两倍，牛牛三倍，葫芦，同花，顺子4倍，其他五倍
10倍封顶, 同花顺10倍，4条9倍，五花牛8倍，五小牛7倍，葫芦6倍，同花，顺子5倍，牛牛4倍，牛9三倍，牛七牛八2倍，无牛到牛六一倍
	 */
	public int getBei(int niuNum) {
		if(niuNum <= 0) {
			return 1;
		}
		if(roomSetting.getBeiTop() == 3) {
			if(niuNum < 7) return 1;
			if(niuNum < 10) return 2;
			return roomSetting.getBeiTop();
		}else if(roomSetting.getBeiTop() == 5) {
			if(niuNum < 7) return 1;
			if(niuNum < 10) return 2;
			if(niuNum == 10) return 3;
			if(niuNum <= DzUtils.HuLu) return 4;
			return roomSetting.getBeiTop();
		}else if(roomSetting.getBeiTop() == 10) {
			if(niuNum < 7) return 1;
			if(niuNum < 9) return 2;
			if(niuNum == 9) return 3;
			if(niuNum == 10) return 4;
			if(niuNum <= DzUtils.TongHua) return 5;
			if(niuNum == DzUtils.HuLu) return 6;
			if(niuNum == DzUtils.WuXiaoNiu) return 7;
			if(niuNum == DzUtils.WuHuaNiu) return 8;
			if(niuNum == DzUtils.ZhanDan) return 9;
			if(niuNum == DzUtils.TongHuaShun) return 10;
			return roomSetting.getBeiTop();
		}
		return 1;
	}
	
	public void setAllPlayerState(UserState state) {
		for (BasePlayer basePlayer : playerList) {
			NnPlayer player = (NnPlayer)basePlayer;
			if(player.getState() != state) {
				player.setState(state);
				if(state == UserState.WaitBet) {
					player.nnInfo.qiangScore = 0;
				}else if(state == UserState.Bet) {
					player.nnInfo.betScore = 1;
				}else if(state == UserState.FapaiComplete) {
					player.showCard();
//					JsonMessage message = new JsonMessage(MessageComm.S2C_ShowNiu);
//					message.addProperty("userId", player.getUserId());
//					message.addProperty("hand", player.getShowCards());
//					message.addProperty("niuNum", player.niuNum);
//					broadcast(message);
				}
			}
		}
	}
	
	public static void main(String[] args) {
		List<Integer> infoList = Lists.newArrayList(3,1,2);
		Collections.sort(infoList, new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1 - o2;
			}
		});
		System.err.println(infoList);
	}
}
